//
// Created by chaseaishang on 23-5-9.
//


//
// Created by chaseaishang on 23-4-28.
//
#include "Render/Renderer.h"
#include "imgui.h"
#include "Event.h"
#include "KeyEvent.h"



#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "TestMorelights.h"
//#include "TestLight.h"
#include "keyCodes.h"
#include "Render/Texture.h"
test::TestMorelights::~TestMorelights()
{

}
test::TestMorelights::TestMorelights()
        :m_Proj(glm::ortho(0.0f, 960.0f, 0.0f, 720.0f, -400.0f, 400.0f)),
         m_View(glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0)))
{

    GLCall(glEnable(GL_BLEND));
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    GLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
    //glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
    float positions[] = {
            //back                            normal             texture
            -0.5f, -0.5f, -0.5f, 0,0,-1,   0.0f,0.0f,// 0
            0.5f, -0.5f, -0.5f,0,0,-1,  1.0f,0.0f,//1
            0.5f,  0.5f, -0.5f, 0,0,-1,1.0f,1.0f,// 2
            -0.5f,  0.5f, -0.5f,0,0,-1,0.0f,1.0f,//3
            // front
            -0.5f, -0.5f,  0.5f,0,0,1,0.0f,0.0f,//4
            0.5f, -0.5f,  0.5f,0,0,1,1.0f,0.0f,//5
            0.5f,  0.5f,  0.5f,0,0,1,1.0f,1.0f,//6
            -0.5f,  0.5f,  0.5f, 0,0,1, 0.0f,1.0f,                     //7
            //left
            -0.5f,  -0.5f,  -0.5f,-1,0,0,0.0f,0.0f,//8
            -0.5f,  -0.5f, 0.5f,-1,0,0,1.0f,0.0f,//9
            -0.5f, 0.5f, 0.5f,-1,0,0,1.0f,1.0f,//10
            -0.5f, 0.5f,  -0.5f,-1,0,0,0.0f,1.0f,//11
            //right
            0.5f,  -0.5f,  0.5f,1,0,0,0.0f,0.0f,//12
            0.5f,  -0.5f, -0.5f,1,0,0,1.0f,0.0f,//13
            0.5f, 0.5f, -0.5f,1,0,0,1.0f,1.0f,//14
            0.5f, 0.5f,  0.5f,1,0,0,0.0f,1.0f,//15
            //bottom
            -0.5f, -0.5f, -0.5f,0,-1,0,0.0f,0.0f,//16
            0.5f, -0.5f, -0.5f,0,-1,0,1.0f,0.0f,//17
            0.5f, -0.5f,  0.5f,0,-1,0,1.0f,1.0f,//18
            -0.5f, -0.5f,  0.5f,0,-1,0,0.0f,1.0f,//19
            //top
            -0.5f,  0.5f, 0.5f,0,1,0,0.0f,0.0f,//20
            0.5f,  0.5f, 0.5f,0,1,0,1.0f,0.0f,//21
            0.5f,  0.5f,  -0.5f,0,1,0,1.0f,1.0f,//22
            -0.5f,  0.5f,  -0.5f,0,1,0,0.0f,1.0f,//23
    };
    unsigned int indices[] = {
            //back
            0, 1, 2,
            2, 3, 0,
            //front
            4,5,6,
            6,7,4,
            //left
            8,9,10,
            10,11,8,
            //right
            12,13,14,
            14,15,12,
            //bottom
            16,17,18,
            18,19,16,
            //top
            20,21,22,
            22,23,20
    };
    GLCall(glEnable(GL_DEPTH_TEST));
    GLCall(glEnable(GL_BLEND));
    GLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));

    m_VAO = std::make_unique<VertexArray>();

    m_VertexBuffer = std::make_unique<VertexBuffer>(positions, (3+3) * 24* sizeof(float));
    VertexBufferLayout layout;
    layout.Push<float>(3);
    layout.Push<float>(3);
    layout.Push<float>(2);
    m_VAO->AddBuffer(*m_VertexBuffer, layout);

    m_IndexBuffer = std::make_unique<IndexBuffer>(indices, 36);

    m_Shader = std::make_unique<Shader>("../res/shaders/4.1.shader.vs","../res/shaders/4.1.shader.fs");

    m_Light_VAO=std::make_unique<VertexArray>();
    VertexBufferLayout light_layout;
    light_layout.Push<float>(3,5);
    m_Light_VAO->AddBuffer(*m_VertexBuffer, light_layout);
    m_Light_Shader=std::make_unique<Shader>("../res/shaders/light_cube.vs","../res/shaders/light_cube.fs");

    m_Texture = std::make_unique<Texture>("../res/textures/container2.png");
    m_Spec_Texture=std::make_unique<Texture>("../res/textures/container2_specular.png");
    m_Shader->Bind();
    m_Shader->SetUniform1i("material.diffuse", 0);
    m_Shader->SetUniform1i("material.specular", 1);
}



void test::TestMorelights::OnUpdate(float deltaTime)
{
    float r=1.2;
    float l_x= sin(glfwGetTime()) * r;
    float l_z= cos(glfwGetTime() ) *r;
    m_lightPos.x = l_x;
    m_lightPos.y =0.0;
    m_lightPos.z =l_z;
    float velocity=m_Model_MovementSpeed;



    auto m_New_MousePosition=Input::GetMousePositionImpl();


    if(m_mouse.Is_LButonPress())
    {
        float x_last,y_last;
        m_mouse.Get_MousePos(x_last,y_last);
        float xoffset = m_New_MousePosition.first - x_last;
        float yoffset = y_last - m_New_MousePosition.second;
        xoffset*=velocity;
        yoffset*=velocity;

        m_model_trans+=glm::vec3(xoffset,yoffset,0);

    }
    m_mouse.Set_MousePos(m_New_MousePosition.first,m_New_MousePosition.second);


    this->camera.OnUpdate(deltaTime);
}

void test::TestMorelights::OnEvent(Event &e) {
    if(e.IsInCategory(EventCategory::EventCategoryApplication))
    {
        return;
    }
    EventDispatcher dispatcher(e);


    dispatcher.Dispatch<MouseButtonPressedEvent>(GLCORE_BIND_EVENT_FN(test::TestMorelights::OnMouseButtonPressed));
    dispatcher.Dispatch<MouseButtonReleasedEvent>(GLCORE_BIND_EVENT_FN(test::TestMorelights::OnMouseButtonReleased));

    this->camera.OnEvent(e);
    if(e.Handled)
    {
        return;
    }
}

void test::TestMorelights::OnRender() {
    GLCall(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
    GLCall(glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT));

    Renderer renderer;


    glm::vec3 light_pos=m_lightPos;//{1,0.0,0.0}
    glm::vec3 view_pos=camera.GetCamera().GetPosition();
    {


        glm::mat4 model = glm::translate(glm::mat4(1.0f), m_model_trans);
        model = glm::scale(model, glm::vec3(1,1,1)); // a smaller cube
        auto mvp=camera.GetCamera().GetViewProjectionMatrix()*model;

        //-0.5f, -0.5f, -0.5f
        m_Texture->Bind();
        m_Spec_Texture->Bind(1);
        m_Shader->Bind();
        //objectColor;lightingShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);
        //        lightingShader.setVec3("lightColor",  1.0f, 1.0f, 1.0f);
        //uniform vec3 lightColor;  u_model



        m_Shader->SetUniform3f("viewPos", view_pos.x,view_pos.y,view_pos.z);


        m_Shader->SetUniform1f("material.shininess", 32.0f);
        glm::vec3 lightColor;
        lightColor.x = sin(glfwGetTime() * 2.0f);
        lightColor.y = sin(glfwGetTime() * 0.7f);
        lightColor.z = sin(glfwGetTime() * 1.3f);

        glm::vec3 diffuseColor = lightColor   * glm::vec3(0.5f); // 降低影响
        glm::vec3 ambientColor = diffuseColor * glm::vec3(0.8f); // 很低的影响
        m_Shader->SetUniform3f("light.position", light_pos.x,light_pos.y,light_pos.z);
        m_Shader->SetUniform3f("light.ambient", ambientColor.x,ambientColor.y,ambientColor.z);
        m_Shader->SetUniform3f("light.diffuse", diffuseColor.x,diffuseColor.y,diffuseColor.z);
        m_Shader->SetUniform3f("light.specular", 1.0f, 1.0f, 1.0f);

        m_Shader->SetUniformMat4f("u_model", model);
        m_Shader->SetUniformMat4f("u_MVP", mvp);
//uniform vec3 viewPos;
        renderer.Draw(*m_VAO, *m_IndexBuffer, *m_Shader);
    }
    {
        glm::mat4 model = glm::translate(glm::mat4(1.0f), light_pos);
        model = glm::scale(model, glm::vec3(0.2,0.2,0.2)); // a smaller cube
        auto mvp=camera.GetCamera().GetViewProjectionMatrix()*model;
        m_Light_Shader->Bind();
        m_Light_Shader->SetUniformMat4f("u_MVP", mvp);
        renderer.Draw(*m_Light_VAO,*m_IndexBuffer,*m_Light_Shader);
    }


}

void test::TestMorelights::OnImGuiRender() {
    float moveSpeed=this->camera.getMMovementSpeed();
    ImGui::SliderFloat("m_MoveSpeed",&moveSpeed,0,2.5);
    ImGui::SliderFloat("m_Model_MovementSpeed",&m_Model_MovementSpeed,0,0.1);
    //m_Model_MovementSpeed
    this->camera.setMMovementSpeed(moveSpeed);
    ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
}


bool test::TestMorelights::OnMouseButtonPressed(MouseButtonPressedEvent &e)
{
    if(e.GetMouseButton()==CSAS_MOUSE_BUTTON_LEFT)
    {
        this->m_mouse.SetLButtonState(Mouse::State::CSAS_PRESSED);
    }
    else if(e.GetMouseButton()==CSAS_MOUSE_BUTTON_RIGHT)
    {
        this->m_mouse.SetRButtonState(Mouse::State::CSAS_PRESSED);
    }
    return false;
}

bool test::TestMorelights::OnMouseButtonReleased(MouseButtonReleasedEvent &e)
{
    if(e.GetMouseButton()==CSAS_MOUSE_BUTTON_LEFT)
    {
        this->m_mouse.SetLButtonState(Mouse::State::CSAS_RELEASED);
    }
    else if(e.GetMouseButton()==CSAS_MOUSE_BUTTON_RIGHT)
    {
        this->m_mouse.SetRButtonState(Mouse::State::CSAS_RELEASED);
    }
    return false;

}
// unuseful
